using Audio;
using Framework.Timer;
using UnityEngine;

namespace Framework.Audio
{
    [RequireComponent(typeof(AudioSource))]
    public class AudioTrack : MonoBehaviour
    {

        private AudioSource         _audioSource;
        private TimeHandler         _timeHandler;
        private string              _audioName;
        private IAudioSourceHandler _audioSourceHandler;

        [SerializeField]
        private ushort _AudioGroup;

        [SerializeField]
        private float _Volume;

        [SerializeField]
        private float _VolumeOffset;


        public  bool        IsPause;
        private float       CurVolume   => this._Volume * this._VolumeOffset;
        public  bool        IsDone      => this._audioSource.clip == null || (!this.IsPause && !this._audioSource.isPlaying);
        public  AudioSource AudioSource => this._audioSource;
        public  ushort      AudioGroup  => this._AudioGroup;
        public  string      AudioName   => this._audioName;


        /// <summary>
        /// 设置音频音量缩放系数
        /// </summary>
        /// <param name="volumeOffset">[0-1]</param>
        public void SetVolumeOffset(float volumeOffset)
        {
            this._VolumeOffset = volumeOffset;
            if (this._timeHandler?.IsDone ?? true)
            {
                this._audioSource.volume = this.CurVolume;
            }
        }

        /// <summary>
        /// 设置音频音量
        /// </summary>
        /// <param name="volume">[0-1]</param>
        public void SetVolume(float volume)
        {
            this._Volume = volume;
            if (this._timeHandler?.IsDone ?? true)
            {
                // Debug.Log($"设置音量 {this.CurVolume}", this);
                this._audioSource.volume = this.CurVolume;
            }
        }

        /// <summary>
        /// 初始化音频文件
        /// </summary>
        /// <param name="audioSource"></param>
        /// <param name="audioType"></param>
        /// <returns></returns>
        internal AudioTrack Init(AudioSource audioSource, ushort audioGroup, IAudioSourceHandler audioSourceHandler)
        {
            this._audioSourceHandler      = audioSourceHandler;
            this._audioSource             = audioSource;
            this._AudioGroup              = audioGroup;
            this._audioSource.playOnAwake = false;
            return this;
        }

        /// <summary>
        /// 播放指定音频
        /// </summary>
        /// <param name="audioClip"></param>
        /// <param name="volume"></param>
        /// <param name="inTime"></param>
        public void Play(string audioName, float volumeOffset, float volume = 1, float inTime = 0, bool isLoop = false)
        {
            AudioClip audioClip = this._audioSourceHandler.GetAudioClip(this._AudioGroup, audioName);
            if (audioClip != null)
            {
                this._timeHandler?.Kill();
                this.name               = audioClip.name;
                this._audioSource.loop  = isLoop;
                this._audioSource.pitch = 1;
                this._audioSource.clip  = audioClip;
                this._audioName         = audioName;
                this._Volume            = volume;
                this._VolumeOffset      = volumeOffset;
                if (inTime == 0)
                {
                    this._audioSource.volume = this.CurVolume;
                }
                else
                {
                    this._audioSource.volume = 0;
                    this._timeHandler        = GameUpdateMgr.Instance.CreateTimer(inTime, () => this._audioSource.volume = this.CurVolume, f => this._audioSource.volume = f * this.CurVolume);
                }

                this.IsPause = false;
                this._audioSource.Play();
            }
        }

        /// <summary>
        /// 暂停音频
        /// </summary>
        /// <param name="outTime"></param>
        public void Pause(float outTime)
        {
            if (this.IsPause)
            {
                return;
            }

            this.IsPause = true;
            this._timeHandler?.Kill();
            if (outTime == 0)
            {
                this._audioSource.Pause();
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer(outTime, () => { this._audioSource.Pause(); }, f => { this._audioSource.volume = (1 - f) * this.CurVolume; });
            }
        }

        /// <summary>
        /// 恢复音频播放
        /// </summary>
        /// <param name="inTime"></param>
        public void UnPause(float inTime)
        {
            if (!this.IsPause)
            {
                return;
            }

            this.IsPause = false;
            this._timeHandler?.Kill();
            if (inTime == 0)
            {
                this._audioSource.volume = this.CurVolume;
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer(inTime, () => { this._audioSource.volume = this.CurVolume; }, f => { this._audioSource.volume = f * this.CurVolume; });
            }

            this._audioSource.UnPause();
        }

        /// <summary>
        /// 销毁音频
        /// </summary>
        /// <param name="outTime"></param>
        public void Kill(float outTime = 0)
        {
            this._timeHandler?.Kill();
            if (outTime == 0)
            {
                this.OverReset();
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer(outTime, this.OverReset, f => this._audioSource.volume = (1 - f) * this.CurVolume);
            }
        }

        /// <summary>
        /// 重置音频播放器
        /// </summary>
        internal void OverReset()
        {
            this._timeHandler?.Kill();

            this.name = "Audio_Track" + this._AudioGroup;
            if (this._audioSource.isPlaying)
                this._audioSource.Stop();
            this._audioSource.clip = null;
            this._audioSourceHandler.OnAudioInvalid(this._AudioGroup, this._audioName);
            this._audioName                           = null;
            this._audioSource.spatialBlend            = 0;
            this._audioSource.transform.localPosition = Vector3.zero;
        }

    }
}